package com.smssalama.storage.contact;

import java.util.Hashtable;

import com.smssalama.storage.framework.ObjectListener;
import com.smssalama.storage.framework.ObjectStore;
import com.smssalama.storage.framework.ObjectStore.ObjectEnumeration;

/**
 * In-memory map between phone numbers and constacts' names
 * 
 * @author Arnold P. Minde
 *
 */
public class ContactsDisplayNameCache {

	private final Hashtable /* <String phoneNumber, String displayName> */number2Name = new Hashtable();
	private final Hashtable /* <int id, String phoneNumber> */id2Number = new Hashtable();
	private final ObjectStore contactsStore;

	public ContactsDisplayNameCache(ObjectStore contactsStore) {
		this.contactsStore = contactsStore;
		contactsStore.addObjectListener(new ObjectListener() {
			public void objectAdded(ObjectStore store, int recordId) {
				invalidate(recordId);
			}

			public void objectChanged(ObjectStore store, int recordId) {
				invalidate(recordId);
			}

			public void objectDeleted(ObjectStore store, int recordId) {
				invalidate(recordId);
			}
		});
	}

	protected void add(int id, String phoneNumber, String displayName) {
		this.number2Name.put(phoneNumber, displayName);
		this.id2Number.put(new Integer(id), phoneNumber);
	}

	protected void invalidate(int id) {
		String phoneNumber = (String) this.id2Number.get(new Integer(id));
		if (phoneNumber != null) {
			this.number2Name.remove(phoneNumber);
		}
		this.id2Number.remove(new Integer(id));
	}

	protected String resolve(String phoneNumber) {
		final ContactFilter filter = new ContactFilter(null, phoneNumber);
		try {
			ObjectEnumeration enumeration = this.contactsStore.search(filter,
					null);
			try {
				if (enumeration.hasNextObject()) {
					Contact contact = (Contact) enumeration.nextObject();
					return contact.getContactName();
				} else {
					return null;
				}
			} finally {
				enumeration.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	public String getPhoneNumberDisplayName(String phoneNumber) {
		// Try to get from cache
		String displayName = (String) this.number2Name.get(phoneNumber);
		if (displayName == null) {
			displayName = resolve(phoneNumber);
		}
		return displayName != null ? displayName : phoneNumber;
	}
}
